#include "SImageButton.h"

#include <core/ImageMgr.h>
#include <core/StyleMgr.h>

#include <QMouseEvent>
#include <QStyleOption>
#include <QStylePainter>

SImageButton::SImageButton(QWidget* parent, QString imageId, QString objectName,
                           QString iconText)
    : QWidget(parent), m_useBgkColor(false), m_mouseState(normal) {
  if (!imageId.isEmpty()) {
    setImgId(imageId);
  }
  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

  if (!objectName.isEmpty()) {
    setObjectName(objectName);
  }

  if (!iconText.isEmpty()) {
    setIconText(iconText);
  }
}

void SImageButton::mousePressEvent(QMouseEvent* event) {
  m_mouseState = pressed;
  m_curImg = m_imgPressed ? m_imgPressed : m_curImg;
  update();
}

void SImageButton::mouseReleaseEvent(QMouseEvent* e) {
  m_curImg = m_imgNormal;
  if (m_imgHover && rect().contains(e->localPos().toPoint()))
    m_curImg = m_imgHover ? m_imgHover : m_imgNormal;

  clicked(m_index);
  if (rect().contains(e->localPos().toPoint())) {
    m_mouseState = hover;
  }
  update();
}

void SImageButton::enterEvent(QEvent* event) {
  m_mouseState = hover;
  if (m_imgHover) {
    m_curImg = m_imgHover;
  }
  update();
  enterOrLeaved(true);
}

void SImageButton::leaveEvent(QEvent* event) {
  m_mouseState = normal;
  if (m_imgHover) {
    m_curImg = m_imgNormal;
  }
  update();
  enterOrLeaved(false);
}

void SImageButton::paintEvent(QPaintEvent* event) {
  QStylePainter painter(this);

  // 绘制背景色
  if (m_useBgkColor) {
    if (isEnabled()) {
      if (m_mouseState == normal) {
        painter.setBrush(QBrush(m_clrNormal));
      } else if (m_mouseState == hover) {
        painter.setBrush(QBrush(m_clrHover));
      } else if (m_mouseState == pressed) {
        painter.setBrush(QBrush(m_clrPressed));
      }
    } else {
      painter.setBrush(QBrush(m_clrDisabled));
    }
    painter.setPen(Qt::transparent);
    painter.setRenderHint(QPainter::Antialiasing);  // 抗锯齿
    painter.drawRoundedRect(rect(), 2, 2);
  }

  // 绘制ICON图标
  if (!m_curImg) {
    painter.drawText(rect(), "No Img!");
    return;
  }

  QRect rcIcon, rcText;
  rcIcon = rcText = rect();
  if (!m_strIconText.isEmpty()) {
    if (m_imgAlign == Qt::AlignLeft) {
      rcText.setLeft(rcText.left() +
                     (rcText.width() - getIconTextLength()) / 2 +
                     rcText.width() / 6);
    }

    rcText.setRight(rcText.left() + getIconTextLength());
    painter.setPen(StyleMgr::instance().color("TextNormal"));
    painter.drawText(rcText, m_strIconText,
                     QTextOption(Qt::AlignCenter | Qt::AlignVCenter));

    if (m_imgAlign == Qt::AlignRight) {
      rcIcon.setLeft(rcText.right());
    } else if (m_imgAlign == Qt::AlignLeft) {
      rcIcon.setRight(rcText.left());
    }
  }

  int w = m_curImg->width();
  int h = m_curImg->height();
  if (m_imgAlign == Qt::AlignRight) {
    rcIcon.setRect(rcIcon.left() + (rcIcon.width() - w) / 2,
                   rcIcon.top() + (rcIcon.height() - h) / 2 + m_topOffset, w,
                   h);
  } else if (m_imgAlign == Qt::AlignLeft) {
    rcIcon.setRect(rcIcon.right() - w,
                   rcIcon.top() + (rcIcon.height() - h) / 2 + m_topOffset, w,
                   h);
  }

  painter.setRenderHint(QPainter::SmoothPixmapTransform);  // 处理图片失真
  if (isEnabled()) {
    painter.drawImage(rcIcon, *m_curImg);
  } else {
    if (!m_imgDisabled) {
      QPixmap pm = QPixmap::fromImage(*m_imgNormal);
      QStyleOption opt;
      opt.initFrom(this);
      QPixmap pmDisabled =
          style()->generatedIconPixmap(QIcon::Disabled, pm, &opt);
      painter.drawPixmap(rcIcon, pmDisabled);
    } else {
      painter.drawImage(rcIcon, *m_imgDisabled);
    }
  }
}

QSize SImageButton::sizeHint() const {
  if (!m_curImg) return QSize(20, 12);
  return m_curImg->size();
}

void SImageButton::setImg(SImage* img, ImgType type) {
  switch (type) {
    case SImageButton::ImgType::kNormal:
      m_imgNormal = img;
      m_curImg = m_imgNormal;
      break;
    case SImageButton::ImgType::kHover:
      m_imgHover = img;
      break;
    case SImageButton::ImgType::kPressed:
      m_imgPressed = img;
      break;
    case SImageButton::ImgType::kDisabled:
      m_imgDisabled = img;
      break;
    default:
      break;
  }
}

// TODO: should consider how to update the image
// when window is moved to another screen with different dpi
//
void SImageButton::setImgId(QString imageId) {
  if (imageId.isEmpty()) return;

  m_imgNormal = ImgMgr::instance().image(imageId, WidgetStatus::kNormal,
                                         devicePixelRatioF());
  Q_ASSERT_X(m_imgNormal, "SImageButton", "Normal image is lost!");
  m_imgHover = ImgMgr::instance().image(imageId, WidgetStatus::kHover,
                                        devicePixelRatioF());
  m_imgPressed = ImgMgr::instance().image(imageId, WidgetStatus::kPressed,
                                          devicePixelRatioF());
  m_imgDisabled = ImgMgr::instance().image(imageId, WidgetStatus::kDisabled,
                                           devicePixelRatioF());

  m_curImg = m_imgNormal;
  if (rect().contains(mapFromGlobal(QCursor::pos())) && m_imgHover)
    m_curImg = m_imgHover;

  if (!isHidden()) updateGeometry();
}

void SImageButton::setIconText(const QString& text) { m_strIconText = text; }

int SImageButton::getIconTextLength() {
  QFontMetrics metrics(font());
  QRect txtR = metrics.boundingRect(m_strIconText);
  return txtR.width() + 8;
}

void SImageButton::setColor(QColor clrNormal, QColor clrHover,
                            QColor clrPressed, QColor clrDisabled) {
  m_useBgkColor = true;
  m_clrNormal = clrNormal;
  m_clrHover = clrHover;
  m_clrPressed = clrPressed;
  m_clrDisabled = clrDisabled;
  update();
}

void SImageButton::setTopOffset(int offset) { m_topOffset = offset; }
